﻿using System;
using System.Collections.Generic;
using System.Collections.Specialized;
using System.Linq;
using System.Text;
using System.Reflection;

namespace OF.Utility
{
    public static class AssemblyUtil
    {
        /// <summary>
        /// 获取指定项目命名空间的类的方法，并执行该方法  
        /// </summary>
        /// <param name="strNameSpace">类库的命名空间</param>
        /// <param name="MethodName">方法名</param>
        /// <param name="Text">参数</param>
        /// <param name="strclassname">类名</param>
        /// <returns>返回方法的执行结果</returns>
        public static object GetMethodStatic(string strNameSpace, string MethodName, object objParameter, string strclassname)
        {

            ////    1.Load(命名空间名称)，GetType(命名空间.类名)  
            Type type = Assembly.Load(strNameSpace).GetType(strNameSpace + ".BLL." + strclassname);

            ////    2.GetMethod(需要调用的方法名称)  
            MethodInfo method = type.GetMethod(MethodName);

            ////    4.方法需要传入的参数  
            ParameterInfo[] pi = method.GetParameters();//获得方法的参数
            string strParameterType = ""; ;//ParameterType 获取该参数的Type（类型）
            //判断方法的参数数量
            if (pi.Length > 0)
            {
                strParameterType = pi[0].ParameterType.Name.ToLower();//ParameterType 获取该参数的Type（类型）
            }
            else
            {
                return method.Invoke(null, null);

            }
            switch (strParameterType)
            {
                case "int32":
                    objParameter = EConvert.ToInt(objParameter);
                    break;
                case "int64":
                    objParameter = EConvert.ToLong(objParameter);
                    break;
                case "int16":
                    objParameter = EConvert.ToShort(objParameter);
                    break;
            }
            object[] parameters = new object[] { objParameter };
            return method.Invoke(null, parameters);

        }
        public static object SetModelInfo(object newInfo, NameValueCollection frmCol)
        {
            Type Objoldinfo = newInfo.GetType();
            FieldInfo[] finfo_oldlist = Objoldinfo.GetFields(BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Instance | BindingFlags.DeclaredOnly);

            foreach (FieldInfo finfo_old in finfo_oldlist)
            {
                string strInputName = finfo_old.Name.Replace("_", "");
                //判断当前要处理的字段是否是创建时间和更新时间
                if (strInputName == "CreateTime" || strInputName == "UpdateTime")
                {
                    finfo_old.SetValue(newInfo, DateTime.Now);
                    continue;
                }
                //判断当前字段是否为页面的表单，如果不是结束本次循环。
                if (frmCol[strInputName] == null)
                {
                    continue;
                }

                switch (finfo_old.FieldType.ToString())
                {
                    case "System.Int32":
                        finfo_old.SetValue(newInfo, EConvert.ToShort(frmCol[strInputName]));
                        break;
                    case "System.Int64":
                        finfo_old.SetValue(newInfo, EConvert.ToLong(frmCol[strInputName]));
                        break;
                    case "System.Int16":
                        finfo_old.SetValue(newInfo, EConvert.ToShort(frmCol[strInputName]));
                        break;
                    case "System.String":
                        finfo_old.SetValue(newInfo, frmCol[strInputName]);
                        break;
                    case "System.DateTime":
                        finfo_old.SetValue(newInfo, EConvert.ToShort(frmCol[strInputName]));
                        break;
                }
            }
            return newInfo;
        }
      
        /// <summary>  
        /// 反射调用类中的方法  
        /// </summary>  
        /// <param name="MethodName"></param>  
        /// <param name="Text"></param>  
        public static object TestMethodStatic(string MethodName, object Text, string strclassname)
        {
            object objParameter = Text;
            ////    1.Load(命名空间名称)，GetType(命名空间.类名)  
            Type type = Assembly.Load("OF.Component").GetType("OF.Component.BLL." + strclassname);

            ////    2.GetMethod(需要调用的方法名称)  
            MethodInfo method = type.GetMethod(MethodName);

            ////    4.方法需要传入的参数  
            ParameterInfo[] pi = method.GetParameters();//获得方法的参数
            string strParameterType = ""; ;//ParameterType 获取该参数的Type（类型）
            if (pi.Length > 0)
            {
                strParameterType = pi[0].ParameterType.Name.ToLower();//ParameterType 获取该参数的Type（类型）
            }
            switch (strParameterType)
            {
                case "int32":
                    objParameter = EConvert.ToInt(Text);
                    break;
                case "int64":
                    objParameter = EConvert.ToLong(Text);
                    break;
                case "int16":
                    objParameter = EConvert.ToShort(Text);
                    break;
            }
            object[] parameters = new object[] { objParameter };
            return method.Invoke(null, parameters);

        }
        /// <summary>  
        /// 反射调用类中的方法  
        /// </summary>  
        /// <param name="MethodName"></param>  
        /// <param name="Text"></param>  
        public static void TestMethod(string MethodName, object Text, string strclassname)
        {

            ////    1.Load(命名空间名称)，GetType(命名空间.类名)  
            Type type = Assembly.Load("OF.Component").GetType("OF.Component.BLL." + strclassname);

            ////    2.GetMethod(需要调用的方法名称)  
            MethodInfo method = type.GetMethod(MethodName);

            ////    3.调用的实例化方法（非静态方法）需要创建类型的一个实例  
            object obj = Activator.CreateInstance(type);

            ////    4.方法需要传入的参数  
            object[] parameters = new object[] { Text };
            //ParameterInfo[] pi = method.GetParameters();//获得方法的参数
            //for (int i = 0; i < pi.Length; i++)
            //{
            //    string str = pi[i].ParameterType.Name + "   " + pi[i].Name;//ParameterType 获取该参数的Type（类型）
            //}
            ////    5.调用方法，如果调用的是一个静态方法，就不需要第3步（创建类型的实例）  
            ////      相应地调用静态方法时，Invoke的第一个参数为null  
            ////    5.调用方法，如果调用的是一个静态方法，就不需要第3步（创建类型的实例）  
            ////      相应地调用静态方法时，Invoke的第一个参数为null  
            method.Invoke(obj, parameters);

        }
    }
    public static class CustomAttributeHelper
    {
        /// <summary>  
        /// Cache Data  
        /// </summary>  
        private static readonly Dictionary<string, string> Cache = new Dictionary<string, string>();

        /// <summary>  
        /// 获取CustomAttribute Value  
        /// </summary>  
        /// <typeparam name="T">Attribute的子类型</typeparam>  
        /// <param name="sourceType">头部标有CustomAttribute类的类型</param>  
        /// <param name="attributeValueAction">取Attribute具体哪个属性值的匿名函数</param>  
        /// <returns>返回Attribute的值，没有则返回null</returns>  
        public static string GetCustomAttributeValue<T>(this Type sourceType, Func<T, string> attributeValueAction) where T : Attribute
        {
            return GetAttributeValue(sourceType, attributeValueAction, null);
        }

        /// <summary>  
        /// 获取CustomAttribute Value  
        /// </summary>  
        /// <typeparam name="T">Attribute的子类型</typeparam>  
        /// <param name="sourceType">头部标有CustomAttribute类的类型</param>  
        /// <param name="attributeValueAction">取Attribute具体哪个属性值的匿名函数</param>  
        /// <param name="name">field name或property name</param>  
        /// <returns>返回Attribute的值，没有则返回null</returns>  
        public static string GetCustomAttributeValue<T>(this Type sourceType, Func<T, string> attributeValueAction,
            string name) where T : Attribute
        {
            return GetAttributeValue(sourceType, attributeValueAction, name);
        }

        private static string GetAttributeValue<T>(Type sourceType, Func<T, string> attributeValueAction,
            string name) where T : Attribute
        {
            var key = BuildKey(sourceType, name);
            if (!Cache.ContainsKey(key))
            {
                CacheAttributeValue(sourceType, attributeValueAction, name);
            }

            return Cache[key];
        }

        /// <summary>  
        /// 缓存Attribute Value  
        /// </summary>  
        private static void CacheAttributeValue<T>(Type type,
            Func<T, string> attributeValueAction, string name)
        {
            var key = BuildKey(type, name);

            var value = GetValue(type, attributeValueAction, name);

            lock (key + "_attributeValueLockKey")
            {
                if (!Cache.ContainsKey(key))
                {
                    Cache[key] = value;
                }
            }
        }

        private static string GetValue<T>(Type type,
            Func<T, string> attributeValueAction, string name)
        {
            object attribute = null;
            if (string.IsNullOrEmpty(name))
            {
                attribute =
                    type.GetCustomAttributes(typeof(T), false).FirstOrDefault();
            }
            else
            {
                var propertyInfo = type.GetProperty(name);
                if (propertyInfo != null)
                {
                    attribute =
                        propertyInfo.GetCustomAttributes(typeof(T), false).FirstOrDefault();
                }

                var fieldInfo = type.GetField(name);
                if (fieldInfo != null)
                {
                    attribute = fieldInfo.GetCustomAttributes(typeof(T), false).FirstOrDefault();
                }
            }

            return attribute == null ? null : attributeValueAction((T)attribute);
        }

        /// <summary>  
        /// 缓存Collection Name Key  
        /// </summary>  
        private static string BuildKey(Type type, string name)
        {
            if (string.IsNullOrEmpty(name))
            {
                return type.FullName;
            }

            return type.FullName + "." + name;
        }

        //使用方法
        //var cName = typeof(CustomAttributes).GetCustomAttributeValue<NameAttribute>(x => x.Name);
        //var fName = typeof(CustomAttributes).GetCustomAttributeValue<NameAttribute>(x => x.Name, "Address");
    }
    [AttributeUsage(AttributeTargets.All)]
    public sealed class NameAttribute : Attribute
    {
        private readonly string _name;

        public string Name
        {
            get { return _name; }
        }

        public NameAttribute(string name)
        {
            _name = name;
        }
    }
}
